from apps.system.kuai100.baseViews import *
from apps.interface.client.models import Client
from apps.pay.order.dao import OrderDao
from apps.system.kuaidi.dao import KuaidiDao
import urllib.parse


class Kuai100ViewSet(BaseKuai100ViewSet):
    authentication_classes = []
    permission_classes = []

    key = 'NtebGADW2015'  # TODO 客户授权key
    customer = 'B36C9A28B43277E9B9E8066D5D0B5274'  # TODO 查询公司编号

    def get_queryset(self):
        params = getRequestParams(self.request)
        _list = Kuai100Dao().findAll()
        return _list

    @action(methods=['post'], detail=False)
    def querydo(self, request):
        params = getRequestParams(request)
        """
        物流轨迹实时查询
        :param com: 查询的快递公司的编码，一律用小写字母
        :param num: 查询的快递单号，单号的最大长度是32个字符
        :param phone: 收件人或寄件人的手机号或固话（也可以填写后四位，如果是固话，请不要上传分机号）
        :param ship_from: 出发地城市，省-市-区，非必填，填了有助于提升签收状态的判断的准确率，请尽量提供
        :param ship_to: 目的地城市，省-市-区，非必填，填了有助于提升签收状态的判断的准确率，且到达目的地后会加大监控频率，请尽量提供
        :return: requests.Response.text
        """
        try:
            orderId = params.get('orderId')
            if not orderId:
                return Response(response_message('订单号不能为空'))
            order = OrderDao().findOneByOrderId(orderId)
            if order.orderStatus != 'WAIT_RECEIVE' and order.orderStatus != 'FINISH':
                return Response(response_message('订单状态错误'))
            kuai100s = Kuai100Dao().findAll().filter(orderId=orderId)
            if kuai100s.exists():
                kuai100 = kuai100s.first()
                # 如果30分钟内更新过物流信息，直接从数据中查
                if datetime.datetime.now()-kuai100.updateTime < datetime.timedelta(minutes=35):
                    print('30分钟内更新过快递信息', kuai100.content)
                    return Response(response_success(Kuai100ModelSerializer(kuai100).data))
            print('没有查到快递信息，去调实时查询接口')
            addrinfoDict = {}
            if order.addrinfo:
                addrinfoDict = json.loads(order.addrinfo)
            expressageinfoDict = {}
            if order.expressageinfo:
                expressageinfoDict = json.loads(order.expressageinfo)
            if not expressageinfoDict.get('expressageCompany'):
                return Response(response_message('物流信息缺失'))
            kuaidis = None
            if expressageinfoDict.get('code'):
                kuaidis = KuaidiDao().findAll().filter(code=expressageinfoDict.get('code'))
            else:
                kuaidis = KuaidiDao().findAll().filter(name=expressageinfoDict.get('expressageCompany'))
            if not kuaidis.exists():
                return Response(response_message('无法提供此快递公司的查询服务'))
            # 拆分快递单号
            expressageNum = expressageinfoDict.get('expressageNum')
            separateStrs = [';', '：', ',', '，', '、']
            separateStr = ''
            for separate in separateStrs:
                if separate in expressageinfoDict.get('expressageNum'):
                    separateStr = separate
                    break
            if separateStr:
                expressageNumList = expressageinfoDict.get('expressageNum').split(separateStr)
                if len(expressageNumList)>0:
                    expressageNum = expressageNumList[0]
            kuaidi = kuaidis.first()
            param = {
                'com': kuaidi.code,
                'num': expressageNum,
                'phone': addrinfoDict.get('contactPhone'),
                'from': '',
                'to': '',
                'resultv2': '1',  # 添加此字段表示开通行政区域解析功能。0：关闭（默认），1：开通行政区域解析功能，2：开通行政解析功能并且返回出发、目的及当前城市信息
                'show': '0',  # 返回数据格式。0：json（默认），1：xml，2：html，3：text
                'order': 'desc'  # 返回结果排序方式。desc：降序（默认），asc：升序
            }
            print('发起实时查询', param)
            param_str = json.dumps(param)  # 转json字符串

            # 签名加密， 用于验证身份， 按param + key + customer 的顺序进行MD5加密（注意加密后字符串要转大写）， 不需要“+”号
            temp_sign = param_str + self.key + self.customer
            md = hashlib.md5()
            md.update(temp_sign.encode())
            sign = md.hexdigest().upper()
            request_data = {'customer': self.customer, 'param': param_str, 'sign': sign}
            url = 'https://poll.kuaidi100.com/poll/query.do'  # 请求地址
            result = requests.post(url, request_data).text  # 发送请求
            result = json.loads(result)
            print('result', result)
            if result.get('result') == False:
                return Response(response_message('未查询到物流信息，请稍后再试！'))
            kuai100s = Kuai100Dao().findAll().filter(orderId=orderId)
            obj = None
            if kuai100s.exists():
                kuai100 = kuai100s.first()
                obj = Kuai100Dao().update(kuai100.id, {'content': json.dumps(result.get('data')), 'state': result.get('state'), 'ischeck': result.get('ischeck')})
            else:
                data = {
                    'orderId': orderId,
                    'addrinfo': addrinfoDict.get('addrInfo'),
                    'content': json.dumps(result.get('data')),
                    'user': order.user.id,
                    'expressageCompany': expressageinfoDict.get('expressageCompany'),
                    'expressageNum': expressageNum,
                    'state': result.get('state'),
                    'ischeck': result.get('ischeck')
                }
                obj = Kuai100Dao().create(data)
        except Exception as e:
            print('实时查询异常', e)
        return Response(response_success(Kuai100ModelSerializer(obj).data))

    '''订阅'''
    @action(methods=['post'], detail=False)
    def poll(self, request):
        params = getRequestParams(request)
        orderId = params.get('orderId')
        if not orderId:
            return Response(response_message('订单号不能为空'))
        client_model = Client.objects.get(clientname=params.get('clientname'))
        order = OrderDao().findOneByOrderId(orderId)
        if order.orderStatus != 'WAIT_RECEIVE' and order.orderStatus != 'FINISH':
            return Response(response_message('订单状态错误'))
        
        expressageinfoDict = {}
        if order.expressageinfo:
            expressageinfoDict = json.loads(order.expressageinfo)
        if not expressageinfoDict.get('expressageCompany'):
            return Response(response_message('物流信息缺失'))
        kuaidis = KuaidiDao().findAll().filter(name__contains=expressageinfoDict.get('expressageCompany'))
        if not kuaidis.exists():
            return Response(response_action(10001, '快递公司不存在'))
        kuaidi = kuaidis.first()

        
        param = {
            'company': kuaidi.code,
            'number': expressageinfoDict.get('expressageNum'),
            'from': '',
            'to': '',
            'key': self.key,
            'parameters': {
                'callbackurl': client_model.baseUrl + '/api/common/kuaidi100/callback/?orderId='+orderId,  # 回调接口的地址。如果需要在推送信息回传自己业务参数，可以在回调地址URL后面拼接上去，例如：https://www.baidu.com/kd100/callback?orderId=123
                'salt': None,  # 签名用随机字符串。32位自定义字符串。添加该参数，则推送的时候会增加sign给贵司校验消息的可靠性
                'resultv2': '1',  # 添加此字段表示开通行政区域解析功能。0：关闭（默认），1：开通行政区域解析功能
                'autoCom': '0',  # 添加此字段且将此值设为1，则表示开始智能判断单号所属公司的功能，开启后，company字段可为空,即只传运单号（number字段），我方收到后会根据单号判断出其所属的快递公司（即company字段）。建议只有在无法知道单号对应的快递公司（即company的值）的情况下才开启此功能
                'interCom': '0',  # 添加此字段且将此值设为1，则表示开启国际版，开启后，若订阅的单号（即number字段）属于国际单号，会返回出发国与目的国两个国家的跟踪信息，本功能暂时只支持邮政体系（国际类的邮政小包、EMS）内的快递公司，若单号我方识别为非国际单，即使添加本字段，也不会返回destResult元素组
                'departureCountry': '',  # 出发国家编码，interCom=1的国际单号最好提供该值
                'departureCom': '',  # 出发国家快递公司的编码，interCom=1的国际单号最好提供该值
                'destinationCountry': '',  # 目的国家编码，interCom=1的国际单号最好提供该值
                'destinationCom': '',  # 目的国家快递公司的编码，interCom=1的国际单号最好提供该值
                'phone': ''
            }
        }
        print('param', param)
        req_params = {
            'schema': 'json',  # 查询公司编号
            'param': json.dumps(param)  # 参数数据
        }

        url = 'https://poll.kuaidi100.com/poll'  # 请求地址
        result = requests.post(url, req_params).text  # 发送请求
        print('result', result)
        return Response(response_success('操作成功'))
    
    @action(methods=['post'], detail=False, authentication_classes=[],permission_classes=[])
    def callback(self, request):
        try:
            body = request.body
            body_str = body.decode('utf-8')
            # 分割成键值对
            pairs = body_str.split('&')
            # 解析键值对
            order_dict = {}
            for pair in pairs:
                key, value = pair.split('=')
                order_dict[key] = value
            data = json.loads(urllib.parse.unquote(order_dict.get('param')))
            # 输出解析后的字典
            print('data', data)
            _list = data.get('lastResult').get('data')
            print('list', _list)
            return Response({ "result":True, "returnCode":"200", "message":"成功"})
            res_str = "SUCCESS"
            res_bytes = res_str.encode('utf-8')
            return Response(res_bytes)
        except Exception as e:
            print('快递100订阅回调异常', e)
            res_str = "FAIL"
            res_bytes = res_str.encode('utf-8')
            return Response(res_bytes)
        

    
